package com.jrx.anytxn.reporting.job.xib.config;

import com.jrx.anytxn.accounting.entity.GaVoucherInfo;
import com.jrx.anytxn.common.constant.Constants;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.param.entity.PrCodeTable;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.mapper.ext.ExtPrCodeTableMapper;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.reporting.config.AnyTxnBatchProperties;
import com.jrx.anytxn.reporting.entity.CmInteCoAcctntEntryDtl;
import com.jrx.anytxn.reporting.job.xib.step.AcctntListener;
import com.jrx.anytxn.reporting.job.xib.step.AcctntProcessor;
import com.jrx.anytxn.reporting.job.xib.step.AcctntWriter;
import com.jrx.anytxn.reporting.mapper.ext.ExtCmInteCoAcctntEntryDtlMapper;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.batch.MyBatisCursorItemReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.support.SynchronizedItemStreamReader;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 会计分录明细账
 */
@Configuration
@EnableConfigurationProperties(AnyTxnBatchProperties.class)
@EnableBatchProcessing
public class GenerateAcctntConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(GenerateAcctntConfiguration.class);

    @Resource(name = "bizSqlSessionFactory")
    SqlSessionFactory sqlSessionFactory;
    @Autowired
    public JobBuilderFactory jobBuilderFactory;
    @Autowired
    public StepBuilderFactory stepBuilderFactory;
    @Autowired
    private AnyTxnBatchProperties anyTxnBatchProperties;
    @Autowired
    private AcctntListener acctntListener;
    @Autowired
    private IOrganizationTableService organizationTableService;
    @Autowired
    private AcctntProcessor acctntProcessor;
    @Autowired
    private AcctntWriter acctntWriter;
    @Resource
    private ExtCmInteCoAcctntEntryDtlMapper extCmInteCoAcctntEntryDtlMapper;
    @Resource
    private ExtPrCodeTableMapper extPrCodeTableMapper;
    @Resource
    Environment environment;

    @Bean
    public Job generateAcctntJob() {
        return jobBuilderFactory.get("generateAcctntJob")
                .incrementer(new RunIdIncrementer()).listener(acctntListener)
                .start(generateAcctntStep())
                //.next(modifyEntryDtlStep())
                .build();
    }


    @Bean
    public Step modifyEntryDtlStep() {
        return stepBuilderFactory.get("modifyEntryDtlStep")
                .tasklet(modifyEntryDtlTasklet())
                .build();
    }

    @Bean
    public Tasklet modifyEntryDtlTasklet() {
        return (stepContribution, chunkContext) -> {
            try {
                logger.info("会计分录修数");
                String tenantId = Constants.DEFAULT_TENANT_ID;

                //查询应用启动文件参数，确保仅在特定的激活文件中执行
                logger.info("激活的配置文件: {}", Arrays.toString(environment.getActiveProfiles()));

                final String expectedKeywords = "1012";
                boolean expected = Arrays.stream(environment.getActiveProfiles())
                        .anyMatch(x -> x.endsWith(expectedKeywords));

                if (expected) {
                    //获取业务日期
                    PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(TransBizConstant.DEFAULT_ORG_ID);
                    String businessDate = DateUtils.format(org.getToday());
                    PrCodeTable prCodeTable = extPrCodeTableMapper.selectByTypeIdAndCodeId("MODIFY_DATA_DATE", "entryDate", tenantId);

                    if (Objects.nonNull(prCodeTable) && Objects.equals(prCodeTable.getCodeName(), businessDate)) {
                        logger.info("会计分录为空，开始修数");
                        extCmInteCoAcctntEntryDtlMapper.modifyEntryDtl(DateUtils.format(org.getToday(), DateUtils.DATE_PATTERN));
                        logger.info("会计分录修数完毕");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.warn("会计分录修数失败", e);
            }
            return RepeatStatus.FINISHED;
        };
    }

    @Bean
    public Step generateAcctntStep(){
        return stepBuilderFactory.get("generateAcctntStep")
                .<GaVoucherInfo, CmInteCoAcctntEntryDtl>chunk(anyTxnBatchProperties.getReportingCustomerConfig().getChunkLimit())
                //表示一批处理100
                // 条记录，数据是逐条发送给processor处理的，处理100条记录后，统一返回给writer进行保存处理
                .reader(acctntReader())
                .processor(acctntProcessor)
                .writer(acctntWriter)
                .taskExecutor(new SimpleAsyncTaskExecutor())
                .throttleLimit(anyTxnBatchProperties.getReportingCustomerConfig().getThrottleLimit())//多线程*/
                .build();
    }

    @Bean
    @StepScope
    public SynchronizedItemStreamReader<GaVoucherInfo> acctntReader() {
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(TransBizConstant.DEFAULT_ORG_ID);
        Date businessDate = org.getToday();
        MyBatisCursorItemReader<GaVoucherInfo> billingCursorReader = new MyBatisCursorItemReader<>();
        billingCursorReader.setSaveState(false);
        billingCursorReader.setSqlSessionFactory(sqlSessionFactory);
        billingCursorReader.setQueryId("com.jrx.anytxn.accounting.mapper.ext.ExtVoucherInfoMapper.selectVoucherByDateForBillingBatch");
        Map<String, Object> map = new HashMap<>();
        map.put("businessDate", businessDate);
        billingCursorReader.setParameterValues(map);
        //同步reader   线程安全
        SynchronizedItemStreamReader<GaVoucherInfo> synchronizedItemStreamReader = new SynchronizedItemStreamReader<>();
        synchronizedItemStreamReader.setDelegate(billingCursorReader);
        return synchronizedItemStreamReader;
    }
}
